package com.wly.login.filter;

import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import cn.hutool.jwt.JWTValidator;
import cn.hutool.jwt.signers.JWTSigner;
import cn.hutool.jwt.signers.JWTSignerUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
 * @author wly
 */
@Slf4j
@Component
public class JwtFilter implements Filter {


	// 密钥
	private static final String SECRET = "my-secret-key";

	// 认证
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {

		// 向下转型：使用子类特定方法
		HttpServletRequest httpRequest = (HttpServletRequest) request;
		HttpServletResponse httpResponse = (HttpServletResponse) response;

		// 1. 获取 Token
		String token = httpRequest.getHeader("Authorization");
		if (token == null || token.isEmpty()) {
			// 401
			sendErrorResponse(httpResponse, HttpServletResponse.SC_UNAUTHORIZED, "未登录");
			return;
		}

		// 2. 验证 Token 是否有效
		boolean validateToken = validateToken(token);
		if(!validateToken) {
			// 401
			sendErrorResponse(httpResponse, HttpServletResponse.SC_UNAUTHORIZED, "Token 无效或已过期");
			return;
		}

		// 3. Token 有效，放行请求
		chain.doFilter(request, response);
	}

	// 发送错误响应
	private void sendErrorResponse(HttpServletResponse response, int statusCode, String message) throws IOException {
		response.setStatus(statusCode);
		response.setContentType("application/json");
		response.setCharacterEncoding(StandardCharsets.UTF_8.name());
		response.getWriter().write("{\"error\":\"" + message + "\"}");
	}


	// 验证 Token 是否有效
	private boolean validateToken(String token) {
		try {
			// 使用密钥验证 Token 签名
			JWTSigner signer = JWTSignerUtil.hs256(SECRET.getBytes(StandardCharsets.UTF_8));
			if (!JWTUtil.verify(token, signer)) {
				return false;
			}
			// 解析 Token
			JWT jwt = JWT.of(token);
			// 验证 Token 是否过期
			JWTValidator.of(jwt).validateDate();
			return true;
		} catch (Exception e) {
			// 验证失败
			log.info("================================错误", e.getMessage());
			return false;
		}
	}
}

// ServletRequest request: 请求对象 （请求报文）
// ServletResponse response: 响应对象 （响应报文）